package com.machine.filling.function.main.activity;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.IdRes;
import android.util.Log;

import com.google.gson.Gson;
import com.machine.filling.R;
import com.machine.filling.db.dao.AdDao;
import com.machine.filling.db.dao.CardTempDao;
import com.machine.filling.db.dao.ClientInfoDao;
import com.machine.filling.db.dao.ExceptionOrderDao;
import com.machine.filling.db.dao.GunInfoDao;
import com.machine.filling.db.dao.TempOrderDao;
import com.machine.filling.db.modle.AdModle;
import com.machine.filling.db.modle.CardTempModle;
import com.machine.filling.db.modle.ClientInfoModle;
import com.machine.filling.db.modle.ExceptionOrderModle;
import com.machine.filling.db.modle.GunInfoModle;
import com.machine.filling.db.modle.TempOrderModle;
import com.machine.filling.net.http.network.APIHttpManager;
import com.machine.filling.net.http.network.BaseHttpStringCallback;
import com.machine.filling.net.http.response.ADListResBean;
import com.machine.filling.net.http.response.PayByCashResBean;
import com.machine.filling.net.serialPort.receive.Receive_EndFueling;
import com.machine.filling.net.serialPort.receive.Receive_MachineState;
import com.machine.filling.net.serialPort.receive.Receive_PrepareFueling;
import com.machine.filling.net.serialPort.send.CMD_CardInfo;
import com.machine.filling.net.serialPort.send.CMD_Confirm_Order;
import com.machine.filling.net.serialPort.send.CMD_SetKaJi;
import com.machine.filling.net.serialPort.send.CMD_SetMachine;
import com.machine.filling.net.serialPort.send.CMD_WriteCard;
import com.machine.filling.net.serialPort.util.SerialPortMsgUtil;
import com.machine.filling.net.serialPort.util.SerialPortSendUtil;
import com.machine.filling.net.serialPort.util.SerialPortTool;
import com.machine.filling.net.serialPort.util.SerialPortToolManager;
import com.machine.filling.net.ws.network.APIWsManager;
import com.machine.filling.net.ws.network.IWebSocketCallback;
import com.machine.filling.net.ws.response.BaseWsResponseBean;
import com.machine.filling.net.ws.response.WsResCardInfoBean;
import com.machine.filling.net.ws.response.WsResLockGunBean;
import com.machine.filling.net.ws.response.WsResPayByCard;
import com.machine.filling.net.ws.response.WsResSelfBean;
import com.machine.filling.net.ws.response.WsResTopGunsInfoBean;
import com.machine.filling.net.ws.response.WsResUnLockGunBean;
import com.machine.filling.net.ws.response.WsResUnSelfBean;
import com.machine.filling.util.Common;
import com.machine.filling.util.CustomToast;
import com.machine.filling.util.DateUtils;
import com.machine.filling.util.FileUtils;
import com.machine.filling.util.HexUtils;
import com.machine.filling.util.SpUtils;
import com.machine.filling.util.StringUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Response;
import okhttp3.WebSocket;
import okio.ByteString;

/**
 * Created by sperfan on 2018/3/1.
 *
 * @描述: IWebSocketCallback：websocket的接口： 连接、接收数据、失败  onOpen  onMessage  onFinalFailureResult
 * OnSerialPortDataReceiveListener 串口通信的接口：
 */
@Deprecated
public class MainFuelPresenter2 implements MainFuelContract.Presenter, IWebSocketCallback, SerialPortTool.OnSerialPortDataReceiveListener {
    private static final String TAG = "MainFuelPresenter";
    private int loopGetGunInfoTime = 10 * 1000;//循环获取油枪信息的时间间隔
    private static final int DEFAULT_LOOPGETADINFO_TIME = 60 * 1000;//循环获取广告信息的间隔时间(时间最好很长)
    private int loopGetADInfoTime = DEFAULT_LOOPGETADINFO_TIME;//轮询获取广告信息的时间是由 广告所有的播放时长之和决定的.

    private static final int RETRY_TIMES = 1;

    private Context mContext;
    private MainFuelContract.View mView;

    private APIWsManager apiWsManager;
    private Handler gunInfoLoopHandler;
    private Handler adListHandler;
    private Handler mDownLoadHandler;
    private Runnable getGunInfoRunnable;
    private Runnable adListRunnable;

    private WsResTopGunsInfoBean.OilGunOutputBean oilGunOutputLeftBean;
    private WsResTopGunsInfoBean.OilGunOutputBean oilGunOutputRightBean;
    private WsResTopGunsInfoBean gunsInfoBean;

    private Map<String, Integer> port_frameIdMap;//串口号与framelayout 的id 的映射对应关系<串口号,framlayouot的id>
    private Map<String, WsResTopGunsInfoBean.OilGunOutputBean> port_beanMap;
    private Map<String, Boolean> serialNumAndIsSelf;//串口号和是否自助关系映射

    /**
     * 获取 串口号对应的 ui的 framelayout id
     *
     * @return
     */

    public
    @IdRes
    int getFramLayoutIdBySerialNum(String serialNum) {
        return port_frameIdMap.get(serialNum);
    }

    public MainFuelPresenter2(Context mContext, MainFuelContract.View mView) {
        this.mContext = mContext;
        this.mView = mView;
        port_frameIdMap = new HashMap<>();
        port_beanMap = new HashMap<>();
        serialNumAndIsSelf = new HashMap<>();
    }

    @Override
    public void start() {

    }

    @Override
    public void distoryContext() {

    }

    /**
     * 单次获取油枪信息
     */
    private void getGunsInfo() {
        mView.showProgress(null);
        ClientInfoModle client = ClientInfoDao.getInstance().getModleByDeviceNum();
        APIHttpManager.getInstance().getTopGunsInfo(client.getToken(),
                client.getMachineId(), new BaseHttpStringCallback() {
                    @Override
                    public void onSuccess(Call call, String result) {
                        gunsInfoBean = new Gson().fromJson(result, WsResTopGunsInfoBean.class);
                        //更新油枪表的 价格
                        mView.showTopGunsInfoResult(gunsInfoBean);
                        mView.showGunsCountUI(gunsInfoBean.getOilGunOutput().size());
                        if (gunsInfoBean.getOilGunOutput().size() == 1) {
                            oilGunOutputLeftBean = gunsInfoBean.getOilGunOutput().get(0);
                            ClientInfoDao.getInstance().updataStationName(oilGunOutputLeftBean.getSellerName());
                            GunInfoDao.getInstance().updateGunInfoFromTop(oilGunOutputLeftBean);
                            SerialPortToolManager.getInstance().openSerialPort(oilGunOutputLeftBean.getPortNum(), MainFuelPresenter2.this);
                            port_frameIdMap.put(oilGunOutputLeftBean.getPortNum(), R.id.frame_left);
                            port_beanMap.put(oilGunOutputLeftBean.getPortNum(), oilGunOutputLeftBean);
                        }
                        if (gunsInfoBean.getOilGunOutput().size() > 1) {
                            //顺序需要反转,
                            oilGunOutputLeftBean = gunsInfoBean.getOilGunOutput().get(1);
                            GunInfoDao.getInstance().updateGunInfoFromTop(oilGunOutputLeftBean);
                            SerialPortToolManager.getInstance().openSerialPort(oilGunOutputLeftBean.getPortNum(), MainFuelPresenter2.this);
                            port_frameIdMap.put(oilGunOutputLeftBean.getPortNum(), R.id.frame_left);
                            port_beanMap.put(oilGunOutputLeftBean.getPortNum(), oilGunOutputLeftBean);

                            oilGunOutputRightBean = gunsInfoBean.getOilGunOutput().get(0);
                            GunInfoDao.getInstance().updateGunInfoFromTop(oilGunOutputRightBean);
                            SerialPortToolManager.getInstance().openSerialPort(oilGunOutputRightBean.getPortNum(), MainFuelPresenter2.this);
                            port_frameIdMap.put(oilGunOutputRightBean.getPortNum(), R.id.frame_right);
                            port_beanMap.put(oilGunOutputRightBean.getPortNum(), oilGunOutputRightBean);
                        }

                    }

                    @Override
                    public void onFailed(String errorCode, String errorMsg, Exception exception) {
                        CustomToast.showToast(mContext, errorCode);

                    }

                    @Override
                    public void onFinished() {
                        mView.hideProgress();
                    }
                });
    }

    /**
     * 循环获取油枪信息
     */
    @Override
    public void http_GetLoopGunInfo() {
        gunInfoLoopHandler = new Handler();
        getGunInfoRunnable = new Runnable() {
            @Override
            public void run() {
                getGunsInfo();
                gunInfoLoopHandler.postDelayed(this, loopGetGunInfoTime);
            }
        };
        gunInfoLoopHandler.post(getGunInfoRunnable);//每几秒执行一次runnable.
    }

    @Override
    public void http_upadteWorkMode(String portNum, boolean isSelf) {
        ClientInfoModle client = ClientInfoDao.getInstance().getModleByDeviceNum();
        GunInfoModle gun = GunInfoDao.getInstance().queryBytPortNum(portNum);
        APIHttpManager.getInstance().updateWorkMode(client.getToken(), gun.getGunId(), isSelf, new BaseHttpStringCallback() {
            @Override
            public void onSuccess(Call call, String result) {
                Log.d(TAG, "更新工作模式====: " + result);
            }

            @Override
            public void onFailed(String errorCode, String errorMsg, Exception exception) {

            }

            @Override
            public void onFinished() {

            }
        });
    }

    @Override
    public void downLoadFiles(List<ADListResBean.AdListBean> httpAdBeans, List<ADListResBean.AdListBean> needDownBeans) {

    }

    /**
     * 通过串口号 获取对应的bean
     *
     * @param portNum
     * @return
     */
    public WsResTopGunsInfoBean.OilGunOutputBean getOilGunBeanByPortNum(String portNum) {
        for (WsResTopGunsInfoBean.OilGunOutputBean bean : gunsInfoBean.getOilGunOutput()) {
            if (portNum.equals(bean.getPortNum())) {
                return bean;
            }
        }
        return null;
    }

    /**
     * 停止循环获取油枪信息
     */
    @Override
    public void http_stopGetLoopGunInfo() {
        gunInfoLoopHandler.removeCallbacks(getGunInfoRunnable);
    }

    /**
     * 停止获取广告信息
     */
    @Override
    public void http_stopGetAdListInfo() {
        if (adListHandler != null && adListRunnable != null)
            adListHandler.removeCallbacks(adListRunnable);
    }


    /**
     * 创建油卡加油的订单
     *
     * @param portNum
     * @param cmd_end
     */
    public void http_create_order_CardFueling(final String portNum, final String orderNum, final Receive_EndFueling cmd_end, final int reTryTimes) {
//        if (reTryTimes > RETRY_TIMES) {
//            // TODO: 2018/4/1 0001 三次尝试创建订单,都失败了,(修改,只有一次了)
//            Log.d(TAG, "创建订单第: " + reTryTimes + "次");
//            return;
//        }
//        final int retryCount = reTryTimes + 1;
        CardTempModle card = CardTempDao.getInstance().queryByPortNum(portNum);

        String amount = "";
        String discountPrice = "";
        String mlAmount = "";

        if (Common.IS_EXCETPION_ORDER_USE) {
            ExceptionOrderModle orderModle = ExceptionOrderDao.getInstance().queryByPortNum(portNum);
            // 实付总金额=油品促销价*加油数量-优惠金额
            amount = orderModle.getAmount();
            //优惠金额
            discountPrice = orderModle.getDiscountPrice();
            //加油量 单位为ml  即*1000
            mlAmount = HexUtils.formatDouble(Double.parseDouble(orderModle.getMlAmount()) * 1000, 2);

        } else {
            TempOrderModle orderModle = TempOrderDao.getInstance().queryByPortNum(portNum);
            // 实付总金额=油品促销价*加油数量-优惠金额
            amount = orderModle.getPayTotalMoney();
            //优惠金额
            discountPrice = orderModle.getDiscountMoney();
            //加油量 单位为ml  即*1000
            mlAmount = HexUtils.formatDouble(Double.parseDouble(orderModle.getFuelVolume()) * 1000, 2);

        }


        GunInfoModle gun = GunInfoDao.getInstance().queryBytPortNum(portNum);
        ClientInfoModle client = ClientInfoDao.getInstance().getModleByDeviceNum();
        if (Common.IS_EXCETPION_ORDER_USE) {
            ExceptionOrderDao.getInstance().upadteOrderNum(portNum, orderNum);
        } else {
            TempOrderDao.getInstance().upadteOrderNum(portNum, orderNum);
        }


        APIHttpManager.getInstance().createNewOrder(
                client.getToken(),
                amount + "", ClientInfoDao.getInstance().getModleByDeviceNum().getMachineNum(),
                discountPrice + "",
                orderNum,
                gun.getPotId(), gun.getGunNum(),
                gun.getGunId() + "",
                gun.getStationId(),
                gun.getMachineId(),
                card.getCardId(),
                gun.getPrice() + "",
                mlAmount,
                gun.getTypeName(),
                gun.getTypeId(),
                gun.getCuPrice() + "",
                gun.getPotNum(),
                Common.COMMIT_ORDER_NORMAL,
                Integer.parseInt(SpUtils.getInstance(mContext).getPingZhengHao(), 16) + "",
                DateUtils.getCurrentTimeYMDHMS(),
                new BaseHttpStringCallback() {
                    @Override
                    public void onSuccess(Call call, String result) {
                        //订单更新订单的上传状态
                        if (Common.IS_EXCETPION_ORDER_USE) {
                            ExceptionOrderDao.getInstance().updateOrderUploadState(portNum, true, "");
                        } else {
                            TempOrderDao.getInstance().setOrderUploadState(portNum, true);
                        }
                        mView.showCreateOrderByOilCard(portNum, cmd_end, true, "");

                    }

                    @Override
                    public void onFailed(String errorCode, String errorMsg, Exception exception) {
//                        http_create_order_CardFueling(portNum, orderNum, cmd_end, retryCount);
//                        if (reTryTimes == RETRY_TIMES) {
                        //订单更新订单 上传状态
                        if (Common.IS_EXCETPION_ORDER_USE) {
                            ExceptionOrderDao.getInstance().updateOrderUploadState(portNum, false, errorMsg);
                        } else {
                            TempOrderDao.getInstance().setOrderUploadState(portNum, false);
                        }
                        //创建订单失败,显示失败界面
                        mView.showCreateOrderByOilCard(portNum, cmd_end, false, errorMsg);
//                        }
                    }

                    @Override
                    public void onFinished() {

                    }
                }
        );
    }

    /**
     * 预约订单的提交
     *
     * @param portNum
     * @param orderNum
     * @param cmd_end
     * @param reTryTimes
     */
    public void http_OrderedOrderCommit(final String portNum, final String orderNum, final Receive_EndFueling cmd_end, final int reTryTimes) {
        if (reTryTimes > 3) {
            // TODO: 2018/4/1 0001 三次尝试创建订单,都失败了,
            CustomToast.showToast(mContext, "订单提交失败,已保存至本地");
            Log.d(TAG, "订单创建失败(尝试" + reTryTimes + "次)");
            return;
        }

        final int retryCount = reTryTimes + 1;

        final double amount = cmd_end.getRealMoney();
        GunInfoModle gun = GunInfoDao.getInstance().queryBytPortNum(portNum);
        ClientInfoModle client = ClientInfoDao.getInstance().getModleByDeviceNum();
        if (Common.IS_EXCETPION_ORDER_USE) {
            ExceptionOrderDao.getInstance().upadteOrderNum(portNum, orderNum);
        } else {
            TempOrderDao.getInstance().upadteOrderNum(portNum, orderNum);

        }
        //加油的量 (ml)
        String mlAmount = Double.parseDouble(HexUtils.ASCII2Str(cmd_end.getSheng_8())) * 1000 + "";
        APIHttpManager.getInstance().caretePreOrder(
                client.getToken(),
                orderNum,
                gun.getGunId(),
                client.getMachineId(),
                gun.getPotId(),
                gun.getGunNum(),
                gun.getTypeId(),
                amount + "",
                gun.getPrice() + "",
                mlAmount,
                client.getMachineNum(),
                gun.getTypeName(),
                gun.getCuPrice(),
                gun.getPotNum(),
                Integer.parseInt(SpUtils.getInstance(mContext).getPingZhengHao(), 16) + "",//凭证号
                Common.COMMIT_ORDER_NORMAL,
                DateUtils.getCurrentTimeYMDHMS(),
                new BaseHttpStringCallback() {
                    @Override
                    public void onSuccess(Call call, String result) {

                        mView.showPreOrderCreate(portNum, cmd_end, true, "");
                    }

                    @Override
                    public void onFailed(String errorCode, String errorMsg, Exception exception) {

                        http_OrderedOrderCommit(portNum, orderNum, cmd_end, retryCount);
                        if (reTryTimes == 3) {
                            //订单更新订单状态
                            if (Common.IS_EXCETPION_ORDER_USE) {
                                ExceptionOrderDao.getInstance().updateOrderUploadState(portNum, false, errorMsg);
                            } else {
                                TempOrderDao.getInstance().setOrderUploadState(portNum, false);
                            }

                            //创建订单失败,显示失败界面
                            mView.showPreOrderCreate(portNum, cmd_end, false, errorMsg);
                        }
                    }

                    @Override
                    public void onFinished() {

                    }
                }

        );
    }

    /**
     * 创建订单  含预约订单提交  和 油卡加油订单创建
     *
     * @param portNum
     * @param cmd_end
     * @param reTryTimes
     */
    public void createOrder(final String portNum, final Receive_EndFueling cmd_end, final int reTryTimes) {
        //判断是否是预约加油  1预约 0未预约
        String isOrdered = "";
        if (Common.IS_EXCETPION_ORDER_USE) {
            isOrdered = ExceptionOrderDao.getInstance().queryByPortNum(portNum).getOrderType();
        } else {
            isOrdered = TempOrderDao.getInstance().queryByPortNum(portNum).getOrderType();
        }
        if (Common.ORDER_TYPE_ORDERED.equals(isOrdered)) {
            // TODO: 2018/4/27 0027 预约订单  后台 提交
            http_OrderedOrderCommit(portNum, mView.getPreOrderNumByPortNum(portNum), cmd_end, 0);
        } else {
            // TODO: 2018/4/1 0001 后台创建订单,如果创建订单成功,则调9101命令
            http_create_order_CardFueling(portNum, StringUtil.createOrderNum(), cmd_end, 0);
        }
    }


    /**
     * 油卡支付
     *
     * @param portNum
     */
    @Override
    public void http_payByUserCard(final String portNum) {
        ClientInfoModle client = ClientInfoDao.getInstance().getModleByDeviceNum();
        String token = client.getToken();
        String machineId = client.getMachineId();
        String orderNum = "";
        if (Common.IS_EXCETPION_ORDER_USE) {
            ExceptionOrderModle tempOrder = ExceptionOrderDao.getInstance().queryByPortNum(portNum);
            orderNum = tempOrder.getOrderNum();
        } else {
            TempOrderModle tempOrder = TempOrderDao.getInstance().queryByPortNum(portNum);
            orderNum = tempOrder.getOrderNum();
        }

        APIHttpManager.getInstance().payByCard(token, machineId, orderNum, new BaseHttpStringCallback() {
            @Override
            public void onSuccess(Call call, String result) {
                Log.d(TAG, "onSuccess() returned: " + "油卡支付调用接口成功");
                WsResPayByCard bean = new Gson().fromJson(result, WsResPayByCard.class);
                mView.showPayUserCardSuccess(portNum, bean);
                //更新订单的支付状态
                if (Common.IS_EXCETPION_ORDER_USE) {
                    ExceptionOrderDao.getInstance().updateOrderPayState(portNum, Common.ORDER_PAYED, "");
                } else {
                    TempOrderDao.getInstance().updateOrderPayState(portNum, Common.ORDER_PAYED);
                }

            }

            @Override
            public void onFailed(String errorCode, String errorMsg, Exception exception) {
                //更新订单的支付状态
                if (Common.IS_EXCETPION_ORDER_USE) {
                    ExceptionOrderDao.getInstance().updateOrderPayState(portNum, Common.ORDER_UNPAY, errorMsg);
                } else {
                    TempOrderDao.getInstance().updateOrderPayState(portNum, Common.ORDER_UNPAY);
                }
            }

            @Override
            public void onFinished() {

            }
        });
    }

    /**
     * 现金付账成功
     *
     * @param portNum
     * @param isFromError 是否是因为其他原因 导致的 现金支付
     * @param errorMsg
     */
    @Override
    public void http_payByCash(final String portNum, boolean isFromError, String errorMsg) {
        String orderNum = "";
        if (Common.IS_EXCETPION_ORDER_USE) {
            orderNum = ExceptionOrderDao.getInstance().queryByPortNum(portNum).getOrderNum();
        } else {
            orderNum = TempOrderDao.getInstance().queryByPortNum(portNum).getOrderNum();
        }
        APIHttpManager.getInstance().payByCash(ClientInfoDao.getInstance().getModleByDeviceNum().getToken(),
                ClientInfoDao.getInstance().getModleByDeviceNum().getMachineId(),
                orderNum,
                new BaseHttpStringCallback() {
                    @Override
                    public void onSuccess(Call call, String result) {
                        PayByCashResBean bean = new Gson().fromJson(result, PayByCashResBean.class);
                        mView.showPayByCashSuccess(portNum, bean);
                        if (Common.IS_EXCETPION_ORDER_USE) {
                            ExceptionOrderDao.getInstance().updateOrderPayState(portNum, Common.ORDER_PAYED, "");
                            ExceptionOrderDao.getInstance().upadteOrderPayMode(portNum, Common.PAY_MODE_CASH);
                        } else {
                            TempOrderDao.getInstance().upadteOrderPayMode(portNum, Common.PAY_MODE_CASH);
                        }
                    }

                    @Override
                    public void onFailed(String errorCode, String errorMsg, Exception exception) {
                        mView.showPayByCashFailed(portNum, errorMsg);
                        ExceptionOrderDao.getInstance().updateOrderPayState(portNum, Common.ORDER_UNPAY, errorMsg);
                    }

                    @Override
                    public void onFinished() {

                    }
                });
    }

    /**
     * 修改油机信息 (价格)
     *
     * @param portNum
     */
    @Override
    public void port_sendSetMachine_1104(String portNum, Receive_MachineState cmd_state) {
        CMD_SetMachine setMachine = new CMD_SetMachine();
        setMachine.setGunNum_1(HexUtils.coverStrFromFirst(Integer.parseInt(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 16) + "", 2));
        String cuPrice = GunInfoDao.getInstance().queryBytPortNum(portNum).getCuPrice();
        String cuPriceStr = HexUtils.coverStrFromFirst(HexUtils.formatDouble(Double.parseDouble(cuPrice), 2), 5);
        cuPriceStr = cuPriceStr.replace(".", "");

        setMachine.setUnitPrice_1(cuPriceStr); //6.0-->0600

        setMachine.setMidu_4("00000000");
        setMachine.setTime_7(DateUtils.getCurrentTimeYMDHMS2());

        setMachine.setTypeName_1("00");
        setMachine.setStationName_1("00");
        String frameStr = SerialPortSendUtil.getInstance().getCmd_SetMachine_1104(Common.MACHINE_VERSION,
                HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2),
                setMachine.getHexStr());
        SerialPortToolManager.getInstance().getSerialPortTool(portNum).sendSerialPort(frameStr);
    }

    /**
     * 修改卡机信息价格(可不调用,只调用修改油机信息即可)
     *
     * @param portNum
     */
    @Deprecated
    @Override
    public void port_sendSetCardMachine_910A(String portNum, Receive_MachineState cmd_state) {
        CMD_SetKaJi cmd__setKaJi = new CMD_SetKaJi();
        //枪号
        cmd__setKaJi.setGunNum_2(HexUtils.str2ASCII(HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2), 2));
        String cuPrice = GunInfoDao.getInstance().queryBytPortNum(portNum).getCuPrice();
        String typeName = GunInfoDao.getInstance().queryBytPortNum(portNum).getTypeName();
        String stationName = ClientInfoDao.getInstance().getModleByDeviceNum().getStationName();
        cmd__setKaJi.setPrice_5(HexUtils.str2ASCII(cuPrice, 5));//油价
        // TODO: 2018/4/15 0015 优惠系数
        cmd__setKaJi.setYouhui_4("302E3030");//302E3035 优惠系数
        cmd__setKaJi.setTime_14(HexUtils.str2ASCII(DateUtils.getCurrentTimeYMDHMS2(), 14));//时间
        cmd__setKaJi.setTypeName_8(HexUtils.str2HexStr(typeName));//油品名称
        cmd__setKaJi.setStationName_18(HexUtils.str2HexStr(stationName));//油站名称

        String frameStr = SerialPortSendUtil.getInstance().getCmd_SetKj_910A(Common.MACHINE_VERSION,
                HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2),
                cmd__setKaJi.getHexStr());

        SerialPortToolManager.getInstance().getSerialPortTool(portNum).sendSerialPort(frameStr);
    }

    /**
     * 下发卡信息
     *
     * @param portNum      端口号
     * @param cardInfoBean http获取的卡信息
     * @param cmd_prepare  8101获取到的卡信息
     */
    @Override
    public void port_sendCardInfo_1101(String portNum, WsResCardInfoBean cardInfoBean, Receive_PrepareFueling cmd_prepare) {

        CMD_CardInfo sendCardInfo = new CMD_CardInfo();
        sendCardInfo.setGunNum_2(HexUtils.str2ASCII(cmd_prepare.getGun_num_head_1(), 2));
        String hexCardType = "";
        switch (cardInfoBean.getType()) {// 1用户的加油卡 2员工卡
            case "1":
                hexCardType = "32";//客存卡
                break;
            case "2":
                hexCardType = "34";//员工卡  员工卡优惠是30303030   而不是302e3030
                break;
            default:
                hexCardType = "36";//不可识别
                break;
        }


        if (StringUtil.isNullOrEmpty(cardInfoBean.getPwd())) {
            sendCardInfo.setPwdType_1("30");//无密码
            sendCardInfo.setPwd_6("303030303030");//密码
        } else {
            sendCardInfo.setPwdType_1("31");//有密码
            sendCardInfo.setPwd_6(HexUtils.str2ASCII(cardInfoBean.getPwd(), 6));//密码
        }
        sendCardInfo.setBindCarFlag_1("30");//车号标识
        sendCardInfo.setCarNum_6("303030303030");//车号
        //卡类型
        sendCardInfo.setCarType_1(hexCardType);

        //优惠幅度
        if (Double.parseDouble(cardInfoBean.getCardDiscount()) == 0) {
            sendCardInfo.setDiscount_4(HexUtils.str2ASCII("0", 4));
        } else {
            sendCardInfo.setDiscount_4(HexUtils.str2ASCII(HexUtils.formatDouble(Double.parseDouble(cardInfoBean.getCardDiscount()), 2), 4));
            Log.d(TAG, "优惠金额-------\n--\n--\n: " + HexUtils.str2ASCII(HexUtils.formatDouble(Double.parseDouble(cardInfoBean.getCardDiscount()), 2), 4));
        }

        sendCardInfo.setDepositBalance_10(HexUtils.str2ASCII(cardInfoBean.getBalance(), 10));//存款余额

        String frameStr = SerialPortSendUtil.getInstance().getCmd_SendCardInfo_1101(Common.MACHINE_VERSION,
                HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2),
                sendCardInfo.getHexStr());
        SerialPortToolManager.getInstance().getSerialPortTool(portNum).sendSerialPort(frameStr);
    }

    /**
     * 弹卡,后台服务器找不到卡
     *
     * @param portNum
     * @param cmd_prepare
     */
    @Override
    public void port_sendCardInfo_1101_errorCard(String portNum, Receive_PrepareFueling cmd_prepare) {
        CMD_CardInfo sendCardInfo = new CMD_CardInfo();
        sendCardInfo.setGunNum_2(HexUtils.str2ASCII(cmd_prepare.getGun_num_head_1(), 2));
        sendCardInfo.setPwdType_1("30");//无密码
        sendCardInfo.setPwd_6("303030303030");//密码
        sendCardInfo.setBindCarFlag_1("30");//车号标识
        sendCardInfo.setCarNum_6("303030303030");//车号
        sendCardInfo.setCarType_1("39");//数据库出错
        sendCardInfo.setDiscount_4("302E3030");
        sendCardInfo.setDepositBalance_10("303030303030302E3030");
        String frameStr = SerialPortSendUtil.getInstance().getCmd_SendCardInfo_1101(Common.MACHINE_VERSION,
                HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2),
                sendCardInfo.getHexStr());
        SerialPortToolManager.getInstance().getSerialPortTool(portNum).sendSerialPort(frameStr);
    }

    /**
     * 油卡加油 下发写卡信息
     */
    @Override
    public void port_sendWriteCard_9101(String portNum, Receive_EndFueling cmd_end) {
        CMD_WriteCard writeCard = new CMD_WriteCard();
        writeCard.setLeiji_amount_4(cmd_end.getMoneyCumlative_4());//累计金额
        writeCard.setLeiji_sheng_4(cmd_end.getLitersCumulative_4());//累计升数
        writeCard.setLeiji_fang_4(cmd_end.getLitersCumulative_4());//?????累计平方
        writeCard.setJifen_4("00000000");//????积分
        writeCard.setYuE_4("00000000");//金额余额?????
        writeCard.setFueled_sheng_4("00000000");//加油体积余额?????
        writeCard.setFueled_fang_4("00000000");//加气体积余额??????
        writeCard.setWriteCardFlag_1("01");//是否写卡, 00不谢,01写
        writeCard.setPingzhengCode_4("0000" + cmd_end.getErialNum_2());//凭证号
        String frameStr = SerialPortSendUtil.getInstance().getCmd_WriteCard_9101(Common.MACHINE_VERSION,
                HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2),
                writeCard.getHexStr());

        SerialPortToolManager.getInstance().getSerialPortTool(portNum).sendSerialPort(frameStr);

    }

    /**
     * 下发确认信息
     *
     * @param portNum
     */
    @Override
    public void port_sendComfirmOrder_1002(String portNum, String gunNum, String pingzhengCode) {
        CMD_Confirm_Order order = new CMD_Confirm_Order();
        order.setGunNum_1(gunNum);
        order.setPingzhengCode_2(pingzhengCode);
        String frameStr = SerialPortSendUtil.getInstance().getCmd_WriteCard_9101(
                Common.MACHINE_VERSION,
                HexUtils.coverStrFromFirst(GunInfoDao.getInstance().queryBytPortNum(portNum).getGunNum(), 2),
                order.getHexStr());

        SerialPortToolManager.getInstance().getSerialPortTool(portNum).sendSerialPort(frameStr);

    }

    /**
     * 更新油枪状态
     */
    @Override
    public void httpUpdateState(String portNum) {
        //获取当前油机状态
        String viewCurrentState = mView.getCurrentState(portNum);
        String oilState = Common.OIL_STATE_OFFLINE;//状态 1空闲 2插卡中 3抬枪 4加油中 5挂抢 6结算中 7锁枪 8开枪中 9锁枪中 10离线
        switch (viewCurrentState) {
            case Common.OIL_STATE_FREE://空闲
                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "空闲");
                break;
            case Common.OIL_STATE_FUELING://加油中
                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "加油中");
                break;
            case Common.OIL_STATE_BILLING://加油结束
                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "加油结束");
                break;
            case Common.OIL_STATE_LOCK://锁枪
                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "锁枪");
                break;
            case Common.OIL_STAT_PREPARE://加油前准备
//                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "加油前准备");
                break;
            case Common.OIL_STATE_CARD_IN://授权有卡
                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "插卡中");
                break;
            case Common.OIL_STATE_OFFLINE://离线
                oilState = viewCurrentState;
                Log.d(TAG, "http更新油枪状态: " + "离线");
                return;
        }
        Log.d(TAG, "http更新油枪状态: " + "");
        APIHttpManager.getInstance().updateGunState(ClientInfoDao.getInstance().getModleByDeviceNum().getToken(),
                port_beanMap.get(portNum).getGunId() + "", oilState, new BaseHttpStringCallback() {
                    @Override
                    public void onSuccess(Call call, String result) {
                        Log.d(TAG, "onSuccess() returned: " + "油枪状态后台更新成功");
                    }

                    @Override
                    public void onFailed(String errorCode, String errorMsg, Exception exception) {
                        Log.d(TAG, "onSuccess() returned: " + "油枪状态后台更新失败");
                    }

                    @Override
                    public void onFinished() {

                    }
                });
    }

    //-----------IWebSocketCallback-
    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        Log.d(TAG, "客户端主界面显示ws连接: ");
    }

    @Override
    public void onMessage(WebSocket webSocket, String text, ByteString bytes) {
        Log.d(TAG, "websocke接收到消息: \n...\n...\n...\n..." + text);
        String msgAction;
        try {
            BaseWsResponseBean baseResp = new Gson().fromJson(text, BaseWsResponseBean.class);
            msgAction = baseResp.getAction();
        } catch (Exception e) {
            Log.d(TAG, "handlerWebSocketMessage() 主界面接收Message returned: " + text);
            msgAction = null;
        }
        if (!StringUtil.isNullOrEmpty(msgAction)) {
            handlerWebSocketMessage(msgAction, text, bytes);
        }
    }

    @Override
    public void onFinalFailureResult(WebSocket webSocket, int code, String reason, Response response) {
        //最终连接失败  重试n次后 还是连接失败
        Log.d(TAG, "onWebSocketFinalFailureResult() returned: " + "最终关闭");
    }

    /**
     * 处理websocket返回的信息
     *
     * @param msgAcion
     * @param text
     * @param bytes
     */
    private void handlerWebSocketMessage(String msgAcion, String text, ByteString bytes) {
        switch (msgAcion) {
            case Common.ACT_CREATE_0001:
                //连接成功
                break;
            case Common.ACT_LOCK_GUN_1007://锁枪
                // TODO: 2018/5/11 0011 先判断是否是空闲,如果没有空闲,则等待空闲后再发命令
                WsResLockGunBean lockGunResBean = new Gson().fromJson(text, WsResLockGunBean.class);
                GunInfoModle gunInfo1 = GunInfoDao.getInstance().queryByGunId(lockGunResBean.getGunId());
                port_sendCMD_LockGun(gunInfo1.getPortNum(), "10", gunInfo1.getGunNum());
                break;
            case Common.ACT_UNLOCK_GUN_1008: //开枪
                WsResUnLockGunBean unLockGunBean = new Gson().fromJson(text, WsResUnLockGunBean.class);
                GunInfoModle gunInfo2 = GunInfoDao.getInstance().queryByGunId(unLockGunBean.getGunId());
                port_sendCMD_UnLockGun(gunInfo2.getPortNum(), "10", gunInfo2.getGunNum());
                break;
            case Common.ACT_SELF_1016://自助模式开启
                WsResSelfBean selfResBean = new Gson().fromJson(text, WsResSelfBean.class);
                GunInfoModle gunInfo3 = GunInfoDao.getInstance().queryByGunId(selfResBean.getGunId());
                port_sendCMD_Self(gunInfo3.getPortNum(), "10", gunInfo3.getGunNum(), true);
                break;
            case Common.ACT_UNSELF_1017://非自助模式开启
                WsResUnSelfBean unSelfBean = new Gson().fromJson(text, WsResUnSelfBean.class);
                GunInfoModle gunInfo4 = GunInfoDao.getInstance().queryByGunId(unSelfBean.getGunId());
                port_sendCMD_Self(gunInfo4.getPortNum(), "10", gunInfo4.getGunNum(), false);
                break;
        }
    }
//----------------------------------------------------------------------------------

//------------------------------------------------


    /**
     * 打开websocket
     */
    @Override
    public void ws_openWebscoket() {
        String token = ClientInfoDao.getInstance().getModleByDeviceNum().getToken();
        String machineId = ClientInfoDao.getInstance().getModleByDeviceNum().getMachineId();
        apiWsManager = APIWsManager.getInstance(token, machineId);
        apiWsManager.setWsCallback(this);
    }

    /**
     * 向串口发命令
     *
     * @param serialNum
     * @param data
     */
    @Deprecated
    public void port_sendSerialPortCMDData(String serialNum, String data) {
        SerialPortToolManager.getInstance().sendSerialPortCMD_DATA(serialNum, data);
    }

    /**
     * 锁枪
     *
     * @param serialNum
     * @param versionNum
     * @param gunNum
     */
    @Override
    public void port_sendCMD_LockGun(String serialNum, String versionNum, String gunNum) {
        SerialPortToolManager.getInstance()
                .sendSerialPortCMD_DATA(serialNum, SerialPortSendUtil.getInstance().getCmd_LockGun_1102(versionNum, gunNum));
    }

    /**
     * 解锁油枪
     *
     * @param serialNum
     * @param versionNum
     * @param gunNum
     */
    @Override
    public void port_sendCMD_UnLockGun(String serialNum, String versionNum, String gunNum) {
        SerialPortToolManager.getInstance()
                .sendSerialPortCMD_DATA(serialNum, SerialPortSendUtil.getInstance().getCmd_UnlockGun_1103(versionNum, gunNum));
    }

    @Override
    public void port_sendCMD_Self(String serialNum, String versionNum, String gunNum, boolean isSelf) {
        serialNumAndIsSelf.put(serialNum, isSelf);
        SerialPortToolManager.getInstance()
                .sendSerialPortCMD_DATA(serialNum, SerialPortSendUtil.getInstance().getCmd_IsSelf_910E(versionNum, gunNum, isSelf));
    }

    /**
     * 获取首页广告列表 (每隔一小时,获取一次)
     */
    @Override
    public void http_getAdListDay() {
        adListHandler = new Handler();
        adListRunnable = new Runnable() {
            @Override
            public void run() {
                getAd();
                adListHandler.postDelayed(this, loopGetADInfoTime);
            }
        };
        adListHandler.post(adListRunnable);
//        getAd();
    }


    /**
     * 单次获取广告信息
     */
    public void getAd() {
        Log.d(TAG, "getAd() returned: " + "开始获取广告,等待" + (loopGetADInfoTime / 1000) + "秒后,再次获取");
        ClientInfoModle client = ClientInfoDao.getInstance().getModleByDeviceNum();

        APIHttpManager.getInstance().getAdList(client.getToken(), client.getMachineId(), new BaseHttpStringCallback() {
            @Override
            public void onSuccess(Call call, String result) {
                SpUtils.getInstance(mContext).setAdListResultStr(result);
                ADListResBean resultBean = new Gson().fromJson(result, ADListResBean.class);
                //下载视频和图片文件
                for (ADListResBean.AdListBean adBean : resultBean.getAdList()) {
                    //根据名字判断是否下载过此文件,如果没有下载过就下载
                    boolean isFileExist = FileUtils.isFileExist(adBean.getImgPath()
                            .substring(adBean.getImgPath().lastIndexOf("/") + 1), "XDKJ/ad",true);
                    loopGetADInfoTime += adBean.getTimeLong();
                    if (!isFileExist) {
                        //播放广告 是从下载文件播放的
                        downLoadFiles(adBean.getImgPath(), adBean.getId() + "");
                        AdModle adModle = new AdModle();
                        adModle.setId(adBean.getId());
                        adModle.setTimeLong(adBean.getTimeLong());
                        adModle.setHttpImgPath(adBean.getImgPath());
                        adModle.setTitle(adBean.getTitle());
                        adModle.setType(adBean.getType());
                        adModle.setUpdateD(adBean.getUpdateD());
                        adModle.setLocalImgPath(
                                Environment.getExternalStorageDirectory()
                                        .getAbsolutePath()
                                        + File.separator
                                        + File.separator
                                        + "XDKJ/ad" + File.separator
                                        + adBean.getImgPath().substring(adBean.getImgPath().lastIndexOf("/") + 1));

                        AdDao.getInstance().update(adModle);
                    }else {
                        Log.d(TAG, "onSuccess() returned: " + "广告文件已存在");
                    }
                }
                loopGetADInfoTime = loopGetADInfoTime == 0 ? DEFAULT_LOOPGETADINFO_TIME : loopGetADInfoTime;

                //此处不直接显示广告视频和图片,视频图片都从下载存储的文件中取
                mView.showAdListUI(resultBean);
            }

            @Override
            public void onFailed(String errorCode, String errorMsg, Exception exception) {
                ADListResBean resultBean = SpUtils.getInstance(mContext).getAdListResultBean();
                List<AdModle> all = AdDao.getInstance().getAll();
                List<ADListResBean.AdListBean> adList = new ArrayList<ADListResBean.AdListBean>();
                for (AdModle ad : all) {
                    ADListResBean.AdListBean bean = new ADListResBean.AdListBean();
                    bean.setTimeLong(ad.getTimeLong());
//                    bean.setType(ad.getHttpImgPath().endsWith(".mp4") ? 2 : 1);
                    bean.setType(ad.getType());
                    bean.setImgPath(ad.getLocalImgPath());
                    bean.setUpdateD(ad.getUpdateD());
                    bean.setId(ad.getId());
                    bean.setTitle(ad.getTitle());
                    adList.add(bean);
                    loopGetADInfoTime += ad.getTimeLong();
                }
                loopGetADInfoTime = loopGetADInfoTime == 0 ? DEFAULT_LOOPGETADINFO_TIME : loopGetADInfoTime;
                if (resultBean != null) {
                    resultBean.setAdList(adList);
                    mView.showAdListUI(resultBean);
                }
            }

            @Override
            public void onFinished() {

            }
        });
    }


    /**
     * 串口接收数据
     *
     * @param serialNum
     * @param hexStr
     * @param currentTimeMillions
     */
    @Override
    public void onDataReceive(String serialNum, String hexStr, long currentTimeMillions) {
        FileUtils.saveFile(null, "串口" + serialNum + "接收数据:[" + hexStr + "]", false);
        Log.d(TAG, "\n串口" + serialNum + "接收收据==" + hexStr);
        SerialPortMsgUtil serialPortMsgUtil = new SerialPortMsgUtil();
        serialPortMsgUtil.setOnSerialPortMsgListener(new SerialPortMsgUtil.OnSerialPortMsgListener() {
            @Override
            public void checkFrameError(String serialNum, String frameMsg) {
                FileUtils.saveFile(null, "串口" + serialNum + "解析错误:[" + frameMsg + "]", true);
                //解析错误
                Log.d(TAG, "onSerialPortOffline() returned: " + "解析失败");
                mView.machineStateOffline(serialNum);
            }

            @Override
            public void checkFramePass(String serialNum, String frameMsg) {
                //解析通过
                FileUtils.saveFile(null, "串口" + serialNum + "解析成功:[" + frameMsg + "]", false);
            }

            @Override
            public void onReceivedStateChanged_CMD_2104(String serialNum, Receive_MachineState cmd_state) {
                Log.d(TAG, "油机状态变更: " + cmd_state.getStateStr());

                if ("00".equalsIgnoreCase(cmd_state.getStateStr())) {
                    Log.d(TAG, "onReceivedStateChanged_CMD_2104() returned: " + "空闲");
                    FileUtils.saveFile(null, "串口" + serialNum + "空闲", true);
                    //开机，空闲
                    mView.machineStateFree_00(serialNum, cmd_state);
                } else if ("0F".equalsIgnoreCase(cmd_state.getStateStr())) {
                    FileUtils.saveFile(null, "串口" + serialNum + "加油中", true);
                    //加油中。。
                    mView.machineStateFueling_0F(serialNum, cmd_state);
                    //开始创建本地订单

                } else if ("0A".equalsIgnoreCase(cmd_state.getStateStr())) {
                    Log.d(TAG, "onReceivedStateChanged_CMD_2104() returned: " + "锁机");
                    FileUtils.saveFile(null, "串口" + serialNum + "锁机", true);
                    //锁机
                    mView.machineStateLock_0A(serialNum);
                } else if ("02".equalsIgnoreCase(cmd_state.getStateStr())) {
                    Log.d(TAG, "onReceivedStateChanged_CMD_2104() returned: " + "授权有卡");
                    FileUtils.saveFile(null, "串口" + serialNum + "授权有卡", true);
                    //授权有卡
                    mView.machineStateCard_02(serialNum);
                } else {
                    Log.d(TAG, "油卡状态未知: " + cmd_state.getStateStr());
                }
            }

            @Override
            public void onReceivedPrepareFueling_CMD_8101(String serialNum, Receive_PrepareFueling cmd_prepare) {
                //加油前的准备
                Log.d(TAG, "onReceivedStateChanged_CMD_2104() returned: " + "加油前的准备");
                FileUtils.saveFile(null, "串口" + serialNum + "加油前的准备", true);
                mView.machinePrepareFueling(serialNum, cmd_prepare);
            }

            @Override
            public void onReceivedUnKnownCMD(String serialNum, String cmdStr) {
                Log.e(TAG, "出错了: " + "其他命令帧");
            }

            @Override
            public void onReceivedEndFueling_CMD_2101(String serialNum, Receive_EndFueling cmd_end) {
                //加油结束
                Log.d(TAG, "onReceivedStateChanged_CMD_2104() returned: " + "加油结束");
                FileUtils.saveFile(null, "串口" + serialNum + "加油结束", true);
                mView.machineEndFueling(serialNum, cmd_end);
            }

            @Override
            public void onPreOrderRes_CMD_110A(String portNum, String datas) {
                //发送定量的返回
                Log.d(TAG, "发送定量返回: " + datas);
                mView.preOrderRes(portNum, datas);
            }

            @Override
            public void onIsSelfRes_CMD_910E(String portNum) {
                //自助非自助返回
                http_upadteWorkMode(portNum, serialNumAndIsSelf.get(portNum));
            }
        });
        serialPortMsgUtil.interceptMessage(serialNum, hexStr);
    }

    @Override
    public void onPortOffLineOutTime(String time, String portNum) {
        //串口5秒未接收到数据,离线
        Log.d(TAG, "onSerialPortOffline() returned: " + "串口离线");
        FileUtils.saveFile(null, "串口" + portNum + "离线:!!", false);
        mView.machineStateOffline(portNum);
    }


    public void downLoadFiles(final String downloadUrl, final String fileName) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int xx = FileUtils.downloadFiles(downloadUrl, "XDKJ" + File.separator + "ad", downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1));
                Log.d(TAG, "下载结果=========: " + xx);
            }
        }).start();
    }
}
